package cn.gailvlun.gll.presentation.chat.vm

import android.arch.lifecycle.ViewModel
import cn.gailvlun.gll.chatkit.dialog.DialogListAdapter.Util.PRE_HAS_EXIT_AT_MESSAGE
import cn.gailvlun.gll.chatlib.Constants
import cn.gailvlun.gll.chatlib.bean.BlockedRoom
import cn.gailvlun.gll.chatlib.db.ChatDB2
import cn.gailvlun.gll.chatlib.dialog.Dialog
import cn.gailvlun.gll.chatlib.message.Message
import cn.gailvlun.gll.chatlib.message.MessageStatus
import cn.gailvlun.gll.chatlib.message.MessageType
import cn.gailvlun.gll.db.DbListRes
import cn.gailvlun.gll.net.Member
import cn.gailvlun.gll.net.apartment.room.ApartmentTask
import cn.gailvlun.gll.net.apartment.room.Room
import cn.gailvlun.gll.net.apartment.room.RoomTag
import cn.gailvlun.gll.net.base.Profile
import cn.gailvlun.gll.util.LogUtil
import cn.gailvlun.gll.util.ProfileUtil
import cn.gailvlun.gll.util.SPUtil
import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.realm.Realm
import io.realm.RealmResults
import io.realm.Sort


class ChatViewModel : ViewModel {

    private var realm: Realm? = null
    var dialogId: String? = null
    var chatId: Int? = null
    var isRoom: Boolean? = false
    var isGroup: Boolean? = false
    var room: Room? = null
    var myMember: Member? = null
    private var user: Profile? = null



    constructor() : super() {
        LogUtil.d("create chatViewModel: $this")
    }

    fun loadInfo(dialogId: String) {
        this.dialogId = dialogId

        val spliced = dialogId.split(":")
        isRoom = spliced[0] == "room"
        chatId = spliced[1].toInt()

        this.realm = Realm.getInstance(ChatDB2.getConfiguration())

        if (isRoom!!) {
            room = realm!!.where(Room::class.java).equalTo("id", chatId).findFirst()
            isGroup = room?.type == "C"
            if (!isGroup!!) {
                myMember = realm!!.where(Member::class.java)
                        .equalTo("room", chatId)
                        .equalTo("owner.id", ProfileUtil.getUserId())
                        .findFirst()
            }
        } else {
            user = realm!!.where(Profile::class.java).equalTo("id", chatId).findFirst()
        }
    }

    fun reloadMyMember() {
        myMember = realm!!.where(Member::class.java)
                .equalTo("room", chatId)
                .equalTo("owner.id", ProfileUtil.getUserId())
                .findFirst()
    }

    fun checkIsChatError(): Boolean {
        if (isRoom!! && room == null) {
            return true
        } else if (!isRoom!! && user == null) {
            return true
        }
        return false
    }

    fun readAllMessage() {
        val results = realm!!.where(Message::class.java)
                .equalTo("dialogId", dialogId)
                .equalTo("unread", true)
                .findAll()
        realm!!.executeTransaction {
            for (msg in results!!) {
                msg.isUnread = false
            }
        }
    }

    fun getChatTitle(): String? {
        return if (isRoom!!) {
            room?.name
        } else {
            user?.name
        }
    }

    
    fun isNeedPromise(): Boolean {
        if (isGroup == true) {
            return false
        }
        if (!isRoom!!) {
            return false
        }
        if (room?.owner?.id == ProfileUtil.getUserId()) {
            return false
        }
        if (myMember?.isIs_promise!!) {
            return false
        }
        return true
    }

    fun isRoomOwner(): Boolean {
        if (!isRoom!!) {
            return false
        }
        if (room?.owner?.id != ProfileUtil.getUserId()) {
            return false
        }
        return true
    }

    fun isRoomOwnerOrLittleOwner(): Boolean {
        if (!isRoom!!) {
            return false
        }
        if (isOwnerOrLittleOwner(room!!, ProfileUtil.getUserId())!!) {
            return false
        }
        return true
    }

    fun isOwnerOrLittleOwner(room: Room, id: Int?): Boolean {
        val isBigHost = room.owner.getId() == id
        var isLittleHost = false
        if (room.small_host_list != null && room.small_host_list.size != 0) {
            for (profile in room.small_host_list) {
                if (profile.getId() == id) {
                    isLittleHost = true
                }
            }
        }
        return isBigHost || isLittleHost
    }

    fun getTaskFlowable(): Flowable<RealmResults<ApartmentTask>> {
        return realm!!.where(ApartmentTask::class.java)
                .equalTo("room", room?.id)
                .sort("sequence_num", Sort.ASCENDING)
                .findAllAsync()
                .asFlowable()
                .filter { it.isLoaded }
                .observeOn(AndroidSchedulers.mainThread())
    }

    fun isAnyCheckInRelateToMe(taskId: Int): Boolean {
        LogUtil.d("isAnyCheckInRelateToMe: realm: $realm")
        return realm!!.where(Message::class.java)
                .equalTo("type", MessageType.checkIn.msgValue)
                .equalTo("taskRecord.task", taskId)
                .beginGroup()
                .equalTo("sender.id", ProfileUtil.getUserId())
                .or()
                .equalTo("taskRecord.couple.owner.id", ProfileUtil.getUserId())
                .endGroup()
                .count() != 0L
    }

    fun isSkillRoom(roomId: Int): Boolean {
        if (isRoom!! && room?.id == roomId && RoomTag.isSkill(room?.tag)) {
            return true
        }
        return false
    }

    fun getCoupleMember(cpMemberId: Int): Member? {
        return realm!!.where(Member::class.java)
                .equalTo("id", cpMemberId)
                .findFirst()
    }

    fun getLatestMessages(): DbListRes<Message> {
        var realmResults = realm!!.where(Message::class.java)
                .equalTo("dialogId", dialogId)
                .sort("created", Sort.DESCENDING)
                .findAll()
        val dbListRes = DbListRes<Message>()
        dbListRes.data = realmResults.subList(0, Math.min(realmResults.size, Constants.Chat.latestMessagesCount))
        dbListRes.isMore = realmResults.size > Constants.Chat.latestMessagesCount
        return dbListRes
    }

    fun getOrderMessage(msg: Message): DbListRes<Message> {
        val realmResults = realm!!.where(Message::class.java)
                .equalTo("dialogId", dialogId)
                .lessThan("created", msg.created)
                .sort("created", Sort.DESCENDING)
                .findAll()

        val dbListRes = DbListRes<Message>()
        dbListRes.data = realmResults.subList(0, Math.min(realmResults.size, Constants.Chat.latestMessagesCount))
        dbListRes.isMore = realmResults.size > Constants.Chat.latestMessagesCount
        return dbListRes
    }

    fun saveMessage(msg: Message) {
        realm!!.executeTransaction { realm ->
            realm.insertOrUpdate(msg)
        }
    }

    fun isMessageSuccess(msg: Message): Boolean {
        val message = realm!!.where(Message::class.java)
                .equalTo("id", msg.id)
                .findFirst()
        return message?.messageStatus == MessageStatus.SUCCESS
    }

    fun getMessageById(msgId: String): Message? {
        return realm!!.where(Message::class.java)
                .equalTo("id", msgId)
                .findFirst()
    }

    fun isCheckInMsgRelate2Me(msg: Message): Boolean {
        if (msg.type != MessageType.checkIn) {
            return false
        }
        if (msg.sender.id == ProfileUtil.getUserId() || msg.taskRecord.couple?.owner?.id == ProfileUtil.getUserId()) {
            return true
        }
        return false
    }

    fun getChatCache(): String? {
        return realm!!.where(Dialog::class.java)
                .equalTo("id", dialogId)
                .findFirst()
                ?.draft
    }

    fun saveCache(cache: String?) {
        var dialog = realm!!.where(Dialog::class.java)
                .equalTo("id", dialogId)
                .findFirst()
        if (dialog != null) {
            realm!!.executeTransaction { realm ->
                dialog.draft = cache
            }
        }
    }

    fun modifyStatus(msg: Message, status: MessageStatus) {
        realm!!.executeTransaction {
            msg.messageStatus = status
            it.insertOrUpdate(msg)
        }
    }

    fun setMessageImage(msg: Message, image: String) {
        realm!!.executeTransaction {
            msg.image = image
            it.insertOrUpdate(msg)
        }
    }

    private fun stopAllLoadingMessage() {
        var results = realm!!.where(Message::class.java)
                .equalTo("messageStatus", MessageStatus.FAIL_SPINNER.value)
                .findAll()
        realm!!.executeTransaction {
            for (msg in results) {
                msg.messageStatus = MessageStatus.FAIL_RESEND
                it.insertOrUpdate(msg)
            }
        }
        results = realm!!.where(Message::class.java)
                .equalTo("messageStatus", MessageStatus.UPLOADING.value)
                .findAll()
        realm!!.executeTransaction {
            for (msg in results) {
                msg.messageStatus = MessageStatus.FAIL_UPLOAD
                it.insertOrUpdate(msg)
            }
        }
    }

    fun isBlocked(): Boolean {
        return realm!!.where(BlockedRoom::class.java)
                .equalTo("roomId", room?.id)
                .findFirst()
                ?.run {
                    return@run true
                } ?: false
    }

    fun getCleanProfile(profile: Profile): Profile {
        return realm!!.copyFromRealm(profile)
    }

    override fun onCleared() {
        readAllMessage()
        if (isRoom!!) {
            SPUtil.put(SPUtil.USER, PRE_HAS_EXIT_AT_MESSAGE + "-" + room?.id, false)
        }
        stopAllLoadingMessage()

        realm?.close()
        realm = null

        LogUtil.d("onCleared: $this --- $realm")

        super.onCleared()
    }
}